package com.diandian.backend.file.service;

import com.diandian.backend.file.resp.FileInfoRespFile;
import com.diandian.backend.file.resp.MultiFileUploadResp;
import com.diandian.backend.file.utils.FileTransferUtil;
import com.diandian.backend.file.utils.FileUtil;
import com.diandian.base.boot.starter.exception.DefaultException;
import com.diandian.base.boot.starter.response.BaseResult;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 本地文件存储操作
 */
@Service
public class LocalFileService extends AbsFileService {

    private static final Logger logger = LoggerFactory.getLogger(LocalFileService.class);

    @Autowired
    private FileCheckService fileCheckService;

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

    @Value("${file.local.singleDirectoryMaxFileCount:''}")
    private int singleDirectoryMaxFileCount;

    @Value("${file.local.allowedExtension:''}")
    private String allowedExtension;

    @Value("${file.local.storagePath:''}")
    private String storagePath;

    @Value("${file.local.maxFileSize:''}")
    private long maxFileSize;

    @Override
    public FileInfoRespFile saveFile(MultipartFile file) {

        // 2. 校验文件格式是否允许
        String fileOriginalName = file.getOriginalFilename();
        String extension = FilenameUtils.getExtension(fileOriginalName);
        if(!fileCheckService.extensionCheck(extension, allowedExtension)){
            return new FileInfoRespFile(false, "暂不支持" + extension + "格式的文件");
        }

        // 3. 文件大小校验
        if(!fileCheckService.fileSizeCheck(file, maxFileSize)){
            return new FileInfoRespFile(false, "文件大小超过限制");
        }

        // 4. 存储根路径检测
        if(!storagePathCheck()){
            return new FileInfoRespFile(false, "存储根路径不合法");
        }

        // 根据时间计算文件夹层级
        String timePath = storagePath + File.separator + sdf.format(new Date());
        File timeDirectory = new File(timePath);
        if(!timeDirectory.exists()){
            logger.info(timePath + "文件夹不存在，创建文件夹");
            timeDirectory.mkdirs();
        }

        // 计算数量层级，超过指定数量则产生新的文件夹
        String countDirectoryName = FileUtil.getMaxNameDirectory(timePath, singleDirectoryMaxFileCount);

        // 计算最终的文件绝对路径
        String fileName = FilenameUtils.getBaseName(fileOriginalName) + "_" + UUID.randomUUID() + "." + extension;
        String filePath = timePath + File.separator + countDirectoryName + File.separator + fileName;
//        logger.info("将要保存文件{} ...", filePath);

        // 6. 执行保存
        boolean saveFlag = false;
        String saveMessage = "";
        try {
            file.transferTo(new File(filePath));
            saveFlag = true;
            saveMessage = "success";
        } catch (IOException e) {
            saveMessage = e.getMessage();
            logger.error("本地存储文件时，出错", e);
        }

        // 7. 构建结果对象
        FileInfoRespFile result = new FileInfoRespFile();
        result.setFileOriginalName(fileOriginalName);
        result.setFileSaveName(fileName);
        result.setFilePath(filePath.replace(storagePath, ""));
        result.setCompleteUrl("");
        result.setServerUrl("");
        result.setUploadSuccess(saveFlag);
        result.setUploadMessage(saveMessage);

        // 8. 保存到数据库

        // 9. 返回
        return result;
    }

    public FileInfoRespFile saveFileFromUrl(String fileName, String url) {

        if(fileName == null || "".equals(fileName) || url == null || "".equals(url)){
            throw new DefaultException("参数缺失");
        }

        String targetFileName = fileName.substring(0, fileName.lastIndexOf(".")) + "_" + UUID.randomUUID() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
        String localFilePath = FileTransferUtil.saveToLocalMultiPath(url, storagePath, targetFileName, singleDirectoryMaxFileCount);

        // 构建结果对象
        FileInfoRespFile result = new FileInfoRespFile();
        result.setFileOriginalName(fileName);
        result.setFileSaveName(targetFileName);
        result.setFilePath(localFilePath.replace(storagePath, ""));
        result.setCompleteUrl("");
        result.setServerUrl("");
        result.setUploadSuccess(true);
        result.setUploadMessage("success");

        // 保存到数据库

        // 返回
        return result;
    }

    /**
     * 校验当前文件存储根目录是否合法
     * @return
     */
    private boolean storagePathCheck(){
        if(storagePath == null || "".equals(storagePath)){
            return false;
        }

        File file = new File(storagePath);
        if(!file.exists()){
            return false;
        }
        if(!file.isDirectory()){
            return false;
        }

        return true;
    }

    @Override
    public MultiFileUploadResp multiUpload(MultipartFile file) {
        return null;
    }

    @Override
    public BaseResult delete(String fileId) {
        return null;
    }

    @Override
    public BaseResult deleteByPath(String path) {
        return null;
    }

    @Override
    public String download(String fileId) {
        return "";
    }

    @Override
    public String downloadByPath(String path) {
        return "";
    }

    @Override
    public String watch(String fileId) {
        return "";
    }

    @Override
    public String watchByPath(String path) {
        return "";
    }

    @Override
    public FileInfoRespFile query(String fileId) {
        return null;
    }

    @Override
    public FileInfoRespFile queryByPath(String path) {
        return null;
    }
}
